package com.spring.framework.aop.xml;

import com.spring.framework.aop.xml.advice.AopTargetAdvice;
import com.spring.framework.aop.xml.advice.JoinPointAspectTarget;
import com.spring.framework.aop.xml.around.AopTargetAround;
import com.spring.framework.aop.xml.hello.FirstAopTarget;
import com.spring.framework.aop.xml.order.AopTargetOrder;
import com.spring.framework.aop.xml.param.ParamAspectTarget;
import com.spring.framework.model.learn.ReflectWarning;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Date;
import java.util.List;

/**
 * Aop Test
 *
 * @author xuweizhi
 * @since 2020/12/16 10:18
 */
public class AopTest extends ReflectWarning {


	@Test
	public void test() {
		//1.获取容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("config/aop/spring-aop.xml");
		//2.获取对象
		FirstAopTarget firstAopTarget = (FirstAopTarget) ac.getBean("firstAopTarget");
		//3.尝试调用被代理类的相关方法
		firstAopTarget.target();
		System.out.println("-------------");
		firstAopTarget.target2();
	}

	/**
	 * 相同的order的切面则按照切面从上到下定义顺序先后执行前置通知，反向执行后置通知。
	 */
	@Test
	public void testOrder() {
		//1.获取容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("config/aop/spring-aop-order.xml");
		//2.获取对象
		AopTargetOrder aopTargetOrder = (AopTargetOrder) ac.getBean("aopTargetOrder");
		//3.尝试调用被代理类的相关方法
		aopTargetOrder.target();
	}

	/**
	 * a:before b:method c:after-returning d:after e:exception
	 * 正常： a -> b -> c -> d
	 * a 异常：a -> e -> d
	 * b 异常： a -> b -> e -> d
	 * c 异常: a -> b -> c -> e -> d
	 * d 异常： a -> b -> c -> d -> e
	 */
	@Test
	public void testAdvice() {
		//1.获取容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("config/aop/spring-aop-advice.xml");
		//2.获取对象
		AopTargetAdvice aopTarget4Advice = (AopTargetAdvice) ac.getBean("aopTargetAdvice");
		//3.尝试调用被代理类的相关方法
		aopTarget4Advice.target();
	}


	@Test
	public void aroundAdivce() {
		//1.获取容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("config/aop/spring-aop-around.xml");
		//2.获取对象
		AopTargetAround aopTargetAround = (AopTargetAround) ac.getBean("aopTargetAround");
		//3.尝试调用被代理类的相关方法
		int x = 2;
		int y = 1;
		System.out.println("-----外部调用切入点方法传递的参数: " + x + " " + y);
		int target = aopTargetAround.target(x, y);
		//最终返回值
		System.out.println("-----外部调用切入点方法获取的最终返回值: " + target);
	}

	@Test
	public void jp() {
		//1.获取容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("config/aop/spring-aop-join-point.xml");
		//2.获取对象
		JoinPointAspectTarget joinPointAspectTarget = (JoinPointAspectTarget) ac.getBean("joinPointAspectTarget");
		//3.尝试调用被代理类的相关方法
		List<Integer> xx = joinPointAspectTarget.target("xx", new Date());
		System.out.println(xx);
	}

	@Test
	public void testParam() {
		//1.获取容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("config/aop/spring-aop-param.xml");
		//2.获取对象
		ParamAspectTarget joinPointAspectTarget = (ParamAspectTarget) ac.getBean("paramAspectTarget");
		//3.尝试调用被代理类的相关方法
		ParamAspectTarget paramAspectTarget = joinPointAspectTarget.target(1, new Date(), "x");
		System.out.println(paramAspectTarget);
	}


}
